package com.xyy.saas.payment.query.core.trade.impl;

import com.xyy.saas.payment.adpater.RouteManager;
import com.xyy.saas.payment.callback.core.result.CallbackRunner;
import com.xyy.saas.payment.common.constants.ChannelConstants;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.bo.TransactionResultBO;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.enums.TransactionStatusEnum;
import com.xyy.saas.payment.cores.enums.TransactionTypeEnum;
import com.xyy.saas.payment.cores.param.TransactionParam;
import com.xyy.saas.payment.cores.vo.CallbackResultVo;
import com.xyy.saas.payment.cores.vo.ResultVO;
import com.xyy.saas.payment.dao.mapper.WithdrawOrderMapper;
import com.xyy.saas.payment.dao.model.WithdrawOrder;
import com.xyy.saas.payment.query.core.trade.AbstractTransactionQuery;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;

@Component
@Slf4j
public class TransactionWithdrawQuery extends AbstractTransactionQuery {

    @Resource
    private WithdrawOrderMapper withdrawOrderMapper;
    @Autowired
    private RouteManager routeManager;
    @Autowired
    private CallbackRunner callbackRunner;

    @Override
    protected ResultVO checkParam(TransactionParam param) {
        if(null == param) {
            return ResultVO.create(ResultCodeEnum.PARAM_ERROR);
        }
        if(StringUtils.isBlank(param.getTradeNo())) {
            return ResultVO.create(ResultCodeEnum.TRADE_NOT_EXIT_ERROR);
        }
        if(StringUtils.isBlank(param.getBusinessOrderType())) {
            return ResultVO.createError("businessOrderType 不能为空");
        }
        return ResultVO.createSuccess();
    }

    @Override
    protected TransactionResultBO queryLocalRecord(TransactionParam param) throws PaymentException {
        WithdrawOrder withdrawOrder = withdrawOrderMapper.selectByWithdrawNo(param.getTradeNo());
        if (withdrawOrder == null) {
            throw new PaymentException(ResultCodeEnum.TRADE_NOT_EXIT_ERROR);
        }
        if(WithdrawOrder.STATUS_FAIL.equals(withdrawOrder.getStatus())){
            return TransactionResultBO.build(withdrawOrder.getWithdrawNo(), TransactionStatusEnum.FAIL.getCode(), withdrawOrder.getAmount(), withdrawOrder.getChannel(), DateUtil.dateToLong(withdrawOrder.getSuccessTime()), withdrawOrder.getChannelWithdrawNo(), withdrawOrder.getBusinessWithdrawNo(), null);
        }
        if(WithdrawOrder.STATUS_FINISH.equals(withdrawOrder.getStatus())){
            return TransactionResultBO.build(withdrawOrder.getWithdrawNo(), TransactionStatusEnum.SUCCESS.getCode(), withdrawOrder.getAmount(), withdrawOrder.getChannel(), DateUtil.dateToLong(withdrawOrder.getSuccessTime()), withdrawOrder.getChannelWithdrawNo(), withdrawOrder.getBusinessWithdrawNo(), null);
        }
        return TransactionResultBO.build(param.getTradeNo(), TransactionStatusEnum.TRANSACTING.getCode());
    }

    @Override
    protected boolean checkIfQueryChannel(TransactionResultBO resultBO) {
        // 提现始终请求渠道
        return true;
    }

    @Override
    protected TransactionResultBO queryChannelRecord(TransactionParam param) throws PaymentException {
        WithdrawOrder withdrawOrder = withdrawOrderMapper.selectByWithdrawNo(param.getTradeNo());

        if (withdrawOrder == null) {
            throw new PaymentException(ResultCodeEnum.TRADE_NOT_EXIT_ERROR);
        }

        param.setChannel(ChannelConstants.CHANNEL_AGGREGATE_NAME);
        param.setAccountId(withdrawOrder.getUserId());
        return routeManager.queryTransaction(param);
    }

    @Override
    protected void processChannelRecord(TransactionParam param, TransactionResultBO channelRecord) throws PaymentException{
        WithdrawOrder withdrawOrder = withdrawOrderMapper.selectByWithdrawNo(param.getTradeNo());
        channelRecord.setBusinessOrderNo(withdrawOrder.getBusinessWithdrawNo());

        if(TransactionStatusEnum.SUCCESS.getCode().equals(channelRecord.getStatus())) {
            if(!WithdrawOrder.STATUS_FINISH.equals(withdrawOrder.getStatus())) {
                withdrawOrder.setStatus(WithdrawOrder.STATUS_FINISH);
                withdrawOrder.setSuccessTime(DateUtil.timeToDate(channelRecord.getSuccessTime()));
                int rows = withdrawOrderMapper.updateByPrimaryKey(withdrawOrder);
                if(rows < 1) {
                    log.error("QueryTradeService#queryWithdrawal database error. withdrawOrder:{} ", JSONUtils.toJSON(withdrawOrder));
                    throw new PaymentException(ResultCodeEnum.DATABASE_ERROR);
                }
            }
        } else if (TransactionStatusEnum.REFUNDED.getCode().equals(channelRecord.getStatus())) {
            // 退汇
            if(!WithdrawOrder.STATUS_REFUND.equals(withdrawOrder.getStatus())) {
                withdrawOrder.setStatus(WithdrawOrder.STATUS_REFUND);
                int rows = withdrawOrderMapper.updateByPrimaryKey(withdrawOrder);
                if(rows < 1) {
                    log.error("QueryTradeService#queryWithdrawal database error. withdrawOrder:{} ", JSONUtils.toJSON(withdrawOrder));
                    throw new PaymentException(ResultCodeEnum.DATABASE_ERROR);
                }
            }
        }
    }

    @Override
    protected void callback(TransactionResultBO resultBO) {
        WithdrawOrder withdrawOrder = withdrawOrderMapper.selectByWithdrawNo(resultBO.getTradeNo());
        if(TransactionStatusEnum.SUCCESS.getCode().equals(resultBO.getStatus())) {
            // 成功
            callbackRunner.callback(withdrawOrder.getWithdrawNo(), CallbackResultVo.TYPE_WITHDRAW_SUCCESS, resultBO.getAmount(), withdrawOrder.getFee(), resultBO.getSuccessTime(), withdrawOrder.getCallBackUrl(), null, null, null,  withdrawOrder.getBusinessWithdrawNo());
            return;
        } else if (TransactionStatusEnum.REFUNDED.getCode().equals(resultBO.getStatus())) {
            // 退汇
            callbackRunner.callback(withdrawOrder.getWithdrawNo(), CallbackResultVo.TYPE_WITHDRAW_REFUND, withdrawOrder.getAmount(), withdrawOrder.getFee(), 0L, withdrawOrder.getCallBackUrl(),null, "交易查询", null, withdrawOrder.getBusinessWithdrawNo());
            return;
        } else if (TransactionStatusEnum.FAIL.getCode().equals(resultBO.getStatus())) {
            // 失败
            callbackRunner.callback(withdrawOrder.getWithdrawNo(), CallbackResultVo.TYPE_WITHDRAW_FAIL, withdrawOrder.getAmount(), withdrawOrder.getFee(), 0L, withdrawOrder.getCallBackUrl(),null, "交易查询", null, withdrawOrder.getBusinessWithdrawNo());
            return;
        }
        log.info("AbstractTransactionQuery#callback nothing. TransactionResultBO:{}", JSONUtils.toJSON(resultBO));
    };

    @Override
    public TransactionTypeEnum getTransactionType() {
        return TransactionTypeEnum.WITHDRAW;
    }
}
